const regx = {
  // 仅字母
  onlyChar: {
    regx: /^([a-zA-Z]+)$/,
    msg: '只能输入字母'
  },
  // 只允许字母和下划线
  charUnderline: {
    regx: /^[a-zA-Z_]+$/,
    msg: '只允许字母和下划线'
  },
  // 只允许输入字母，数字，汉字，下划线
  charNumHanUnderline: {
    regx: /^[A-Za-z0-9_\u4E00-\u9FA5]+$/,
    msg: '只允许输入字母，数字，汉字，下划线'
  },
  // 只允许输入字母，数字，汉字
  charNumHan: {
    regx: /^[A-Za-z0-9\u4E00-\u9FA5]+$/,
    msg: '只允许输入字母，数字，汉字'
  },
  // 只允许数字和字母
  charNum: {
    regx: /^[A-Za-z0-9]+$/,
    msg: '只允许数字和字母'
  },
  // 只允许数字和字母中横线或下划线
  charNumLine: {
    regx: /^[A-Za-z0-9_-]+$/,
    msg: '只允许字母、数字、下划线和中横线'
  },
  // 只允许数字和字母
  charNumLineStartWidthChar: {
    regx: /^[A-z][A-z0-9_-]+$/,
    msg: '只允许字母、数字、下划线和中横线,字母开头'
  },
  // 只允许输入字母，汉字
  charHan: {
    regx: /^[A-Za-z\u4E00-\u9FA5]+$/,
    msg: '只允许输入字母，汉字'
  },
  // 只允许数字和下划线
  numUnderline: {
    regx: /^[0-9_]+$/,
    msg: '只允许数字和下划线'
  },
  // 数字、字母（区分大小写）、特殊字符
  numCharSpecial: {
    regx: /[A-z\d!@#$%^&*~\-_=+]+$/,
    msg: '只允许数字、字母、特殊字符'
  },
  // 必须同时包含数字、字母（区分大小写）、特殊字符
  mustNumCharSpecial: {
    regx: /^(?=.*[A-z])(?=.*\d)(?=.*[!@#$%^&*~\-_=+])[A-z\d!@#$%^&*~\-_=+]+$/,
    msg: '必须同时包含数字、字母、特殊字符'
  },
  // 不能输入<>
  expectSpecials: {
    regx: /^[^<>]*$/g,
    msg: '不能输入特殊字符'
  },
  phone: {
    regx: /^([0-9]{3,4}-)?[0-9]{7,8}$/,
    msg: '请输入正确的电话号码'
  },
  mobile: {
    regx: /^1[0-9]{10}$/,
    msg: '请输入正确的手机号码'
  },
  // 同时校验手机和电话
  tel: {
    regx: /^(1[3|4|5|6|7|8|9])\d{9}$|^0\d{2,3}-?\d{7,8}$|^400[016789]\d{6}$|^400-[016789]\d{2}-\d{4}$/,
    msg: '请输入正确的电话号码'
  },
  size: {
    regx: /^\d+(?=(px|%)$)/,
    msg: '值为数字加px或%'
  },
  ipv4: {
    regx: /^(?:25[0-5]|2[0-4]\d|[0-1]?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d{1,2})){3}$/,
    msg: '请输入正确的ipv4地址'
  },
  ipv6: {
    regx: /^([[:xdigit:]]{1,4}(?::[[:xdigit:]]{1,4}){7}|::|:(?::[[:xdigit:]]{1,4}){1,6}|[[:xdigit:]]{1,4}:(?::[[:xdigit:]]{1,4}){1,5}|(?:[[:xdigit:]]{1,4}:){2}(?::[[:xdigit:]]{1,4}){1,4}|(?:[[:xdigit:]]{1,4}:){3}(?::[[:xdigit:]]{1,4}){1,3}|(?:[[:xdigit:]]{1,4}:){4}(?::[[:xdigit:]]{1,4}){1,2}|(?:[[:xdigit:]]{1,4}:){5}:[[:xdigit:]]{1,4}|(?:[[:xdigit:]]{1,4}:){1,6}:)$/,
    msg: '请输入正确的ipv6地址'
  },
  ip: {
    regx: /^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-fA-F]|[a-fA-F][a-fA-F0-9-]*[a-fA-F0-9])\.)*([A-Fa-f]|[A-Fa-f][A-Fa-f0-9-]*[A-Fa-f0-9])$|^(?:(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-fA-F]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,1}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,2}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,3}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:[0-9a-fA-F]{1,4})):)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,4}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,5}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,6}(?:(?:[0-9a-fA-F]{1,4})))?::)))))$/,
    msg: '请输入正确的ip地址'
  },
  positiveInteger: {
    regx: /^[1-9]\d*$/,
    msg: '请输入正整数'
  },
  amount: {
    regx: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/,
    msg: '金额不能为负数，小数位最多2位'
  },
  email: {
    regx: /^[a-zA-Z0-9]+([-_.][A-Za-zd]+)*@([a-zA-Z0-9]+[-.])+[A-Za-zd]{2,5}$/,
    msg: '请输入合法的邮箱'
  },
  // SpecChars: {
  //   regx: /[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~！@#￥%……&*（）——\-+={}|《》？：“”【】、；‘'，。、]/im,
  //   msg: '包含特殊字符'
  // }
  // 至少8个字符，至少1个大写字母，1个小写字母和1个数字
  password: {
    regx: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/,
    msg: '至少8个字符，至少1个大写字母，1个小写字母和1个数字'
  }
}

function getRules(rules) {
  return rules.map(rule => {
    const reg = regx[rule]
    let res
    if (reg) {
      res = {
        pattern: reg.regx,
        message: reg.msg,
        trigger: 'blur'
      }
    }
    return res
  })
}

function getVal(obj, key) {
  const keys = key.split('.')
  let temp = obj
  for (let i = 0, l = keys.length; i < l; i++) {
    temp = temp[keys[i]]
    if (temp === undefined) {
      break
    }
  }
  return temp
}

/**
 * 创建表单值一致性校验，比如密码
 * @param obj
 * @param key
 * @param errMsg
 * @returns {{validator: validator, trigger: string}}
 */
function createEqual(obj, key, errMsg = '两次值不一致!') {
  const validator = (rule, value, callback) => {
    if (value !== getVal(obj, key)) {
      callback(new Error(errMsg))
    } else {
      callback()
    }
  }
  return {
    validator,
    trigger: 'blur'
  }
}

/**
 * 创建唯一性校验，例如联系人的名字
 * @param obj
 * @param listKey
 * @param key
 * @param errMsg
 * @returns {{validator: validator, trigger: string}}
 */
function createUnique(obj, listKey, key, errMsg = '已存在相同值!') {
  const validator = (rule, value, callback) => {
    const list = getVal(obj, listKey) || []

    const filter = list.filter(item => value === getVal(item, key))
    const flag = filter.length > 1

    if (flag) {
      callback(new Error(errMsg))
    } else {
      callback()
    }
  }
  return {
    validator,
    trigger: 'blur'
  }
}

export {
  regx,
  getRules,
  createEqual,
  createUnique
}
